<template>
	<div>
		<div class="container">
			<a-layout>
				<a-layout-sider width="400" theme="light">
					<div class="pe-4">
						<a-card title="城市公司">
							<template #extra>
								<a-input-search
									v-model:value="cityOrProjectSearch"
									placeholder="城市公司/项目"
									style="width: 200px"
									allow-clear
									@search="onSearch"
								/>
							</template>
							<a-tree v-model:selectedKeys="chooseNodes" v-model:expandedKeys="expandedKeys" :field-names="{ title: 'name', key: 'id' }" :auto-expand-parent="true" :tree-data="searchCompanyList" @select="selectTree">
								<template #title="node">
									<span v-html="node.name.replace(cityOrProjectSearch, `<b style=\'color:#f60\'>${cityOrProjectSearch}</b>`)"></span>
								</template>
							</a-tree>
						</a-card>
					</div>
				</a-layout-sider>

				<a-layout-content style="background:#fff">
					<div class="toolbar">
						<a-form ref="searchRef" layout="inline" :model="searchState" @finish="loading=true;initData(chooseNodes[0])">
							<a-form-item label="名称">
								<a-input v-model:value="searchState.name" placeholder="项目/工号" allow-clear></a-input>
							</a-form-item>

							<a-form-item>
								<a-space>
									<a-button type="primary" html-type="submit">
										<search-outlined />搜索
									</a-button>

									<a-tooltip>
										<template #title>请先选择左侧项目</template>
									</a-tooltip>
								</a-space>
							</a-form-item>
						</a-form>
					</div>
					<div class="mt-2">
						<!--获取数据后重新渲染表格，否则defaultExpandAllRows获取动态数据的情况下无效-->
						<a-table v-if="!loading" :columns="columns" :scroll="tableScroll" :pagination="false" :default-expand-all-rows="true" row-key="id" :data-source="dataTree" :loading="loading">
							<template #bodyCell="{ column, record }">
								<template v-if="column.key === 'operation'">
									<a-space>
										<a-button v-permission="200" type="link" @click="addDictionary(record.id)">
											<plus-outlined />添加子数据
										</a-button>

										<a-button v-if="record.dataType === 'gongHao'" v-permission="201" type="link" @click="editDictionary(record)">
											<edit-outlined />修改
										</a-button>
										<a-button v-permission="202" type="link" style="color:#ff7875" @click="deleteGongHao(record, chooseNodes.id)">
											<delete-outlined />删除
										</a-button>
									</a-space>
								</template>
							</template>
						</a-table>
					</div>
				</a-layout-content>
			</a-layout>
			<a-modal v-model:visible="visible" :width="400" :title="`${formState.id ? '修改' : '添加'}数据`" @ok="saveGongHao">
				<a-form ref="formRef" :model="formState" v-bind="{labelCol: { style: { width: '80px' } }}">
					<a-form-item label="名称" name="name" :rules="{required:true, message:'请输入名称'}">
						<a-input v-model:value="formState.name" />
					</a-form-item>
				</a-form>
			</a-modal>
		</div>
	</div>
</template>
<script setup>
import { ref, getCurrentInstance, watch, onMounted, computed } from "vue";
import { post } from "@/utils/index.js";
import { DeleteOutlined, EditOutlined, PlusOutlined, SearchOutlined } from "@ant-design/icons-vue";
const { proxy } = getCurrentInstance();
const rootCompanyList = ref([]);
const searchCompanyList = ref([]);
const chooseNodes = ref([]);
const expandedKeys = ref([]);
const projectList = ref([]);
const cityOrProjectSearch = ref(null);
const searchState = ref({});
const loading = ref(false);
const dataTree = ref([]);
const formState = ref({});
const visible = ref(false);
const formRef = ref();
const columns = [
	{
		title: "ID",
		dataIndex: "id",
		key: "id",
		width: 160,
		align: "left",
		fixed: "left"
	},
	{
		title: "名称",
		dataIndex: "name",
		sorter: false,
		width: 300,
		ellipsis: true
	},
	{},
	{
		title: "操作",
		key: "operation",
		sorter: false,
		fixed: "right",
		width: 240,
		align: "center"
	}
];
const getCompanyOptions = async () => {
	const companyList = await post("department/projects?type=2", {
		parent_ids: JSON.stringify([78, 24])
	});
	rootCompanyList.value = companyList.data.map(d => {
		return {
			id: d.id,
			name: d.name,
			dataType: 'company',
		};
	});
	searchCompanyList.value = rootCompanyList.value;
}
const getProjectOptions = async () => {
	const result = await post("department/projects?type=3");
	projectList.value = result.data.map(d => {
		return {
			key: d.id,
			id: d.id,
			name: d.name,
			dataType: 'project',
			parentIds: d.parent_ids.split(',').map(i => parseInt(i)),
		};
	});
}
const constructCompanyTree = async () => {
	await getProjectOptions();
	const projects = JSON.parse(JSON.stringify(projectList.value))
	if (!rootCompanyList.value.length) {
		rootCompanyList.value = projects;
		searchCompanyList.value = projects;
		return;
	}
	for (const project of projects) {
		for (const company of rootCompanyList.value) {
			if (project.parentIds.includes(company.id)) {
				company.children = company.children || [];
				company.children.push(project);
			}
		}
	}
}
onMounted(async () => {
	await getCompanyOptions();
	await constructCompanyTree();
	chooseNodes.value = [searchCompanyList.value[0]?.id];
	await initData(chooseNodes.value[0], true)
});

const onSearch = () => {
	const searchVal = cityOrProjectSearch.value;
	if (!searchVal) {
		searchCompanyList.value = rootCompanyList.value;
		expandedKeys.value = [];
		return;
	}
	const ergodicTree = (trees, index) => {
		const tree = trees[index];
		if (tree.name.indexOf(searchVal) > -1) {
			return;
		}
		tree.children = tree.children || [];
		for (let i = 0; i < tree.children.length; i++) {
			ergodicTree(tree.children, i);
		}
		tree.children = tree.children.filter(i => i);
		if (tree.children.length) return;
		trees[index] = null;
	}
	const tree = JSON.parse(JSON.stringify(rootCompanyList.value));
	for (let i = 0; i < tree.length; i++) {
		ergodicTree(tree, i);
	}
	searchCompanyList.value = tree.filter(i => i);
	expandedKeys.value = searchCompanyList.value.map(item => item.id);
}
const selectTree = async (selectedKeys, e) => {
	await initData(selectedKeys[0], false);
}
const tableScroll = computed(() => ({
	x: document.documentElement.clientWidth - 680,
	y: document.documentElement.clientHeight - 400
}));

const constructTree = async () => {
	const gongHaoList = (await post("department/projects?type=4")).data;
	gongHaoList.sort((a, b) => a.id - b.id);
	const gongHaoMap = {};
	for (const gongHao of gongHaoList) {
		gongHaoMap[gongHao.id] = {
			key: gongHao.id,
			id: gongHao.id,
			name: gongHao.name,
			isTop: true,
			dataType: 'gongHao',
			parentIds: gongHao.parent_ids.split(','),
			parent_id: gongHao.parent_id,
			parent_ids: gongHao.parent_ids,
		}
		if (gongHaoMap[gongHao.parent_id]) {
			gongHaoMap[gongHao.id].isTop = false;
			if (!gongHaoMap[gongHao.parent_id].children) gongHaoMap[gongHao.parent_id].children = [];
			gongHaoMap[gongHao.parent_id].children.push(gongHaoMap[gongHao.id]);
		}
	}
	const projectListMap = projectList.value.reduce((target, item) => {
		target[item.id] = item;
		return target;
	}, {});
	const projectListKeys = Object.keys(projectListMap);
	for (const key in gongHaoMap) {
		const gongHao = gongHaoMap[key];
		if (!gongHao.isTop) {
			continue;
		}
		for (const treeKey of projectListKeys) {
			if (!gongHao.parentIds.includes(String(treeKey))) continue;
			if (!projectListMap[treeKey].children) projectListMap[treeKey].children = [];
			projectListMap[treeKey].children.push(gongHao);
			break;
		}
	}
}
const initData = async (targetId, reconstructionTree = false) => {
	loading.value = true;
	if (reconstructionTree) {
		await getProjectOptions();
		await constructTree();
	}
	if (rootCompanyList.value.find((item) => item.id === targetId && item.dataType === 'company')) {
		dataTree.value = JSON.parse(JSON.stringify(projectList.value.filter((item) => item.parentIds.includes(targetId))));
	} else {
		dataTree.value = JSON.parse(JSON.stringify(projectList.value.filter((item) => item.id === targetId)));
	}
	if (searchState.value.name) {
		const ergodicTree = (trees, index) => {
			const tree = trees[index];
			if (tree.name.indexOf(searchState.value.name) > -1) {
				return;
			}
			tree.children = tree.children || [];
			for (let i = 0; i < tree.children.length; i++) {
				ergodicTree(tree.children, i);
			}
			tree.children = tree.children.filter(i => i);
			if (tree.children.length) return;
			trees[index] = null;
		}
		for (let i = 0; i < dataTree.value.length; i++) {
			ergodicTree(dataTree.value, i);
		}
	}
	dataTree.value = dataTree.value.filter(i => i);
	setTimeout(() => {
		loading.value = false;
	}, 50)
};
const addDictionary = parentId => {
	formState.value = {
		parent_id: parentId
	};
	visible.value = true;
};
const editDictionary = record => {
	formState.value = { ...record };
	visible.value = true;
};
const deleteGongHao = (record, rootId) => {
	// 递归获取所有子节点id
	const recursionIds = (tree, ids) => {
		ids.push(tree.id);
		if (!tree.children?.length) return;
		for (const children of tree.children) {
			recursionIds(children, ids);
		}
	};
	let content = '';
	const ids = [];
	if (record.dataType === 'project') {
		content = "将删除项目下的所有工号，请谨慎操作";
		for (const children of record.children) recursionIds(children, ids);
	} else {
		content = "将同时删除该工号和工号下的所有子工号，请谨慎操作";
		recursionIds(record, ids);
	}
	proxy.$confirm({
		title: "确认提示",
		content,
		okText: "确认",
		cancelText: "取消",
		onOk() {
			post("department/deletes", { ids: ids.join(','), type: 4 }).then((data) => {
				proxy.$message.success("删除成功");

				initData(rootId, true);
			}).catch((err) => {
				proxy.$message.error(err);
			});
		}
	});
};
const saveGongHao = () => {
	formRef.value
		.validate()
		.then(() => {
			proxy.$message.destroy();

			const params = {
				...formState.value,
				type: 4,
			};

			post("department/save", params)
				.then(data => {
					proxy.$message.success("提交成功", 1);
					visible.value = false;

					initData(chooseNodes.value[0], true);
				})
				.catch(err => {
					proxy.$message.error(err);
				});
		})
		.catch(err => {});
};
watch(visible, value => {
	if (value) formRef.value?.clearValidate();
});
</script>
<style scoped lang="scss">
.container {
  background: #fff;
  padding: 12px;
  height: calc(100vh - 170px);
}

.gongHao-item {
  display: flex;
  justify-content: space-between;

  & + .gongHao-item {
    margin-top: 15px;
  }
}
</style>